/**
 * Crurrying
 * @param { Function } fn 要传入的函数
 * @returns { Function }
 */

// 柯里化函数？
// 是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数，并且返回接受余下的参数且返回结果的新函数的技术
// fn(1, 2) => fn(1)(2)
// 两者输入的结果一致

/**
 * 最基础的柯里化函数
 */
function curry(fn) {
  return function(a) {
    return function(b) {
      return fn(a, b)
    }
  }
}

// 使用
const sum = (a, b) => console.log(a + b)
const curryCopy = curry(sum)
sum(1, 2) // 3
curryCopy(1)(2) // 3

/**
 * 通用柯里化函数的实现
 * fn.length 这边说明一下，函数的长度是指这个函数必填参数的个数
 */
function currying(fn) {
  return function curried(...args) {
    if (args.length >= fn.length) {
      return fn.apply(this, args);
    } else {
      return function(...args2) {
        return curried.apply(this, args.concat(args2));
      }
    }
  };
}

// 举个栗子
const logTypeMap = {
  0: 'INFO',
  1: 'DEBUG',
  2: 'ERR'
};
// 输出日志的函数 带有三个参数
function logs(date, type, msg) {
  console.log(`[${date}] ${logTypeMap[type]} ${msg}`);
}

// 转成柯里化函数
let curriedLogs = currying(logs);
// 固定时间参数 采取偏函数
const nowLogsFn = curriedLogs(new Date())
// curriedLogs(new Date(), 0, '这是一条普通的信息');
nowLogsFn(1, '这是一条测试信息');
nowLogsFn(2)('这是一条报错信息');
